/**
 * 普贴打印小程序 蓝牙 sdk
 * @author zyc
 * @date 2021/05/27
 */
class putyBleUtils {
	_discoveryStarted = false; //是否开始扫描
	deviceId = null; //连接的设备
	deviceName = null; //连接的设备名称
	flag = false; //是否发送中
	oldTime = "";//处理显示进度
	/**
	 * 蓝牙errCode对应错误信息
	 */
	openBluetoothAdapterError = {
		0: "正常",
		"-1": "已连接",
		10000: "未初始化蓝牙适配器",
		10001: "当前蓝牙适配器不可用",
		10002: "没有找到指定设备",
		10003: "连接失败",
		10004: "没有找到指定服务",
		10005: "没有找到指定特征值",
		10006: "当前连接已断开",
		10007: "当前特征值不支持此操作",
		10008: "其余所有系统上报的异常",
		10009: "Android 系统特有，系统版本低于 4.3 不支持 BLE",
		10012: "连接超时",
		10013: "连接 deviceId 为空或者是格式不正确",
	}
	/**
	 * 初始化蓝牙
	 */
	openBluetoothAdapter() {
		return new Promise((resolve, reject) => {
			if (uni.openBluetoothAdapter) {
				uni.openBluetoothAdapter({
					success: (res) => {
						this._discoveryStarted = false;
						resolve(true)
					},
					fail: (res) => {
						reject(this.BluetoothEnum(res))
					}
				})
			} else {
				reject("当前微信版本不支持蓝牙连接，请升级后重试！");
			}
		})
	}
	/**
	 * 停止扫描
	 */
	stopBluetoothDevicesDiscovery() {
		this._discoveryStarted = false;
		uni.stopBluetoothDevicesDiscovery();
	}
	/**
	 * 开始扫描
	 * @param {number} timeOut 毫秒数 默认5000
	 */
	startBluetoothDevicesDiscovery(timeOut = 5000,flag = true) {
		return new Promise((resolve, reject) => {
			if (this._discoveryStarted) {} else {
				this._discoveryStarted = true;
				uni.startBluetoothDevicesDiscovery({
					// services:['49535343-FE7D-4AE5-8FA9-9FAFD205E455'],
					interval: 1000,
					allowDuplicatesKey: true,
					success: (res) => {
						// if(flag){
						// 	uni.startPullDownRefresh(); //下拉刷新
						// }
						// setTimeout(() => {
						// 	if(flag){
						// 		uni.stopPullDownRefresh(); //结束下拉刷新
						// 	}
						// 	this.stopBluetoothDevicesDiscovery(); //停止扫描
						// 	this._discoveryStarted = false;
						// }, timeOut + 1000)
						resolve(res)
					},
					fail: (error) => {
						this._discoveryStarted = false;
						if(error.errCode == 10008){
							reject(error)
						}else{
							reject(this.BluetoothEnum(error))
						}
					}
				})
			}
		})
	}
	/**
	 * 发现设备信息
	 */
	onBluetoothDeviceFound(callback) {
		return new Promise((resolve, reject) => {
			uni.onBluetoothDeviceFound((res) => {
				if (res && res.devices) {
					let blueData = this.unique(res.devices);
					//过滤无用设备
					let devices = blueData.filter(device => device.name && device.name != "未知设备");
						//  && device.name.indexOf('PT-') != -1
					callback(devices)
					resolve(devices)
				}
			})
		})
	}
	/**
	 * 关闭蓝牙模块
	 */
	closeBluetoothAdapter() {
		uni.closeBluetoothAdapter();
		this.deviceId = null;
		this._discoveryStarted = false;
	}
	/**
	 * 蓝牙错误码返回
	 */
	BluetoothEnum(res) {
		if (res.errCode) {
			if (openBluetoothAdapterError[res.errCode]) {
				return openBluetoothAdapterError[res.errCode];
			} else {
				return "未知错误";
			}
		} else {
			return res.errMsg;
		}
	}
	//数组去重
	unique(arr) {
		return Array.from(new Set(arr))
	}

	// 获取在蓝牙模块生效期间所有搜索到的蓝牙设备。包括已经和本机处于连接状态的设备.
	getBluetoothDevices(){
		return new Promise((resolve) => {
			wx.getBluetoothDevices({
				complete:res => {
					resolve(res)
				}
			})
		})
	}
	
	/**
	 * 连接设备
	 * @param {String} deviceId 设备id
	 */
	async createBLEConnection(deviceId,deviceName) {
		return new Promise(async (resolve, reject) => {
			if (!deviceId) {return reject("deviceId不能为空")}
			if(this.deviceId == deviceId){return resolve("重复连接");}
			if(this.deviceId){await this.closeBLEConnection(this.deviceId)}
			try {
				let res = await this.openBluetoothAdapter();
                
				uni.createBLEConnection({
					deviceId,
					timeout:3000,
					success: (res) => {
						setTimeout(()=>{
							uni.getBLEDeviceServices({
								deviceId: deviceId,
								success: (res) => {
									uni.getBLEDeviceCharacteristics({
										deviceId: deviceId,
										serviceId: "49535343-FE7D-4AE5-8FA9-9FAFD205E455",
										success:(res)=>{
                                            
											let sys = uni.getSystemInfoSync()
											if(sys.platform == "ios"){
												this.deviceId = deviceId;
												this.deviceName = deviceName;
												// 连接成功
												resolve("连接成功");
											}else{
												uni.setBLEMTU({
													deviceId:deviceId,
													mtu:182,
													success:(res)=>{
														this.deviceId = deviceId;
														this.deviceName = deviceName;
														resolve("连接成功");
													},fail(error) {
														reject("设置最大传输单元失败");
													}
												})
											}
										},
										fail: (err) => {
                                            uni.removeStorageSync('bleDevice')
                                            
											// 连接失败
											reject("连接失败");
											// this.closeBluetoothAdapter();
										}
									})
								},
								fail: (err) => {
                                    uni.removeStorageSync('bleDevice')
									// 连接失败
									reject("连接失败");
									// this.closeBluetoothAdapter();
								}
							})
						},1000)
					},
					fail: (err) => {
                        uni.removeStorageSync('bleDevice')
						// reject("连接失败")
						reject("连接失败");
						// this.closeBluetoothAdapter();
					}
				})
			} catch (error) {
				reject(error)
			}
		})
	}

	/**
	 * 监听回调
	 */
	readBLECharacteristicValue(callback){
		uni.readBLECharacteristicValue({
			deviceId: this.deviceId,
			serviceId: "49535343-FE7D-4AE5-8FA9-9FAFD205E455",
			characteristicId: "49535343-8841-43F4-A8D4-ECBE34729BB3",
			success: function (res) {
				callback && typeof callback(res)
			}
		})
	}

	/**
	 * 发送ESC数据
	 */
	async printEsc(data,callback){
		return new Promise(async (resolve,reject) => {
			if(this.flag){return reject("等待上一指令发送结束，再进行发送")}
			if(!uni.setBLEMTU){return reject("当前微信版本过低，请升级后重试")}
			if(!this.deviceId){return reject("未连接设备")}
			const mtu = 182;
			const offset = 28;
			this.dataToSubcontract(this.deviceId,data,0,mtu - 3,resolve,reject,callback,offset);
		})
	}

	/**
	 * 发送数据
	 */
	async printCpcl(data,callback){
		await this.printEsc(data,callback)
	}

	/**分包发送CPCL数据 */
	dataToSubcontract(deviceId,dataBytes,i,sendNumber,resolve,reject,callback,offset){
		var index = parseInt(dataBytes.length / sendNumber) * sendNumber > dataBytes.length ? parseInt(dataBytes.length / sendNumber) : parseInt(dataBytes.length / sendNumber) + 1;
		var data = dataBytes.slice(i * sendNumber, (i + 1) == index ? dataBytes.length : (i + 1) * sendNumber);
		let buffer = new Uint8Array(data).buffer;
		this.oldTime = new Date().getTime()
		if (i < index) {
            
            
			uni.writeBLECharacteristicValue({
                writeType: "writeNoResponse",
				deviceId: deviceId,
				serviceId: "49535343-FE7D-4AE5-8FA9-9FAFD205E455",
				characteristicId: "49535343-8841-43F4-A8D4-ECBE34729BB3",
				value: buffer,
				success: res => {
					let timeOutDiff = new Date().getTime() - this.oldTime;
					setTimeout(()=>{
						this.dataToSubcontract(deviceId,dataBytes,++i,sendNumber,resolve,reject,callback,offset);
					},offset)
					// const interval = setInterval(() => {
					// 	this.dataToSubcontract(deviceId,dataBytes,++i,sendNumber,resolve,reject,callback,offset);
					// 	clearInterval(interval)
					// }, offset - timeOutDiff >= 0 ? offset - timeOutDiff : 0);
				},
				fail: error => {
					if(error.errCode != 0 && error.errCode != undefined){
						reject(error.errMsg);
					}
				},
				complete: () => {
					if(callback){typeof callback && callback(parseInt(i * 100 / index))}
				}
			})
		}else{
			resolve(true);
			if(callback){typeof callback && callback(100)}
		}
	}
}
export default new putyBleUtils();
